package com.acegear.horizon.domain.models;

import com.acegear.horizon.ApplicationContextProvider;
import com.acegear.horizon.domain.events.*;
import com.acegear.horizon.domain.events.processers.EventProcessor;
import com.acegear.horizon.domain.models.constraint.ClubMemberType;
import com.acegear.horizon.domain.models.constraint.UserPostType;
import com.acegear.horizon.domain.models.jpa.ClubBase;
import com.acegear.horizon.domain.models.jpa.ClubEventMember;
import com.acegear.horizon.domain.models.jpa.ClubMember;
import com.acegear.horizon.domain.models.jpa.ContentPart;
import com.acegear.horizon.domain.models.jpa.DefaultSettings;
import com.acegear.horizon.domain.models.jpa.EventLike;
import com.acegear.horizon.domain.models.jpa.PasswordAuth;
import com.acegear.horizon.domain.models.jpa.PostLike;
import com.acegear.horizon.domain.models.jpa.UserAuth;
import com.acegear.horizon.domain.models.jpa.UserEmail;
import com.acegear.horizon.domain.models.jpa.UserFollow;
import com.acegear.horizon.domain.models.jpa.UserInfo;
import com.acegear.horizon.domain.models.jpa.UserPhone;
import com.acegear.horizon.domain.models.jpa.WechatAuth;
import com.acegear.horizon.domain.models.jpa.WeiboAuth;
import com.acegear.horizon.domain.models.vo.ClubEventVO;
import com.acegear.horizon.domain.models.vo.FollowVO;
import com.acegear.horizon.domain.models.vo.UserCommentPostVO;
import com.acegear.horizon.domain.models.vo.UserInfoTokenVO;
import com.acegear.horizon.domain.models.vo.UserPostVO;
import com.acegear.horizon.domain.models.vo.UserProfileVO;
import com.acegear.horizon.domain.repository.ClubEventRepository;
import com.acegear.horizon.domain.repository.ClubRepository;
import com.acegear.horizon.domain.repository.CommentRepository;
import com.acegear.horizon.domain.repository.PostRepository;
import com.acegear.horizon.domain.repository.jpa.ClubBaseRepository;
import com.acegear.horizon.domain.repository.jpa.ClubEventMemberRepository;
import com.acegear.horizon.domain.repository.jpa.ClubMemberRepository;
import com.acegear.horizon.domain.repository.jpa.EventLikeRepository;
import com.acegear.horizon.domain.repository.jpa.EventOrderRepository;
import com.acegear.horizon.domain.repository.jpa.PasswordAuthRepository;
import com.acegear.horizon.domain.repository.jpa.PostLikeRepository;
import com.acegear.horizon.domain.repository.jpa.SecureTokenRepository;
import com.acegear.horizon.domain.repository.jpa.UserAuthRepository;
import com.acegear.horizon.domain.repository.jpa.UserEmailRepository;
import com.acegear.horizon.domain.repository.jpa.UserEquipRepository;
import com.acegear.horizon.domain.repository.jpa.UserFollowRepository;
import com.acegear.horizon.domain.repository.jpa.UserInfoRepository;
import com.acegear.horizon.domain.repository.jpa.UserPhoneRepository;
import com.acegear.horizon.domain.repository.jpa.WechatAuthRepository;
import com.acegear.horizon.domain.repository.jpa.WeiboAuthRepository;
import com.acegear.horizon.domain.services.FollowService;
import com.acegear.horizon.domain.services.KongService;
import com.acegear.horizon.domain.services.PictureService;
import com.acegear.horizon.domain.services.UserService;

import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * Created by wangsike on 2016/12/17.
 */
public class User {

    private Long userId;

    private UserAuth userAuth;
    
    private Long clubId;

    // private String defaultAvatar = "https://img.acegear.com/2017/2/5/5ac8197d-05c4-42c5-8c06-c20a70c2d4cd/w700";
    private PasswordAuth passwordAuth;
    private UserEmail userEmail;
    private UserPhone userPhone;
    private UserInfo userInfo;
    private UserInfoRepository userInfoRepository;
    private PasswordAuthRepository passwordAuthRepository;
    private WeiboAuthRepository weiboAuthRepository;
    private WechatAuthRepository wechatAuthRepository;
    private UserAuthRepository userAuthRepository;
    private UserPhoneRepository userPhoneRepository;
    private UserEmailRepository userEmailRepository;
    private SecureTokenRepository secureTokenRepository;
    private ClubRepository clubRepository;
    private UserFollowRepository userFollowRepository;
    private PostRepository postRepository;
    private PostLikeRepository postLikeRepository;
    private EventLikeRepository eventLikeRepository;
    private CommentRepository commentRepository;
    private ClubEventMemberRepository clubEventMemberRepository;
    private ClubEventRepository clubEventRepository;
    private ClubBaseRepository clubBaseRepository;
    private ClubMemberRepository clubMemberRepository;
    private EventOrderRepository eventOrderRepository;
    private UserEquipRepository userEquipRepository;
    private ModelFactory modelFactory;
    private UserService userService;
    private EventProcessor eventProcessor;
    private KongService kongService;
    private PictureService pictureService;
    private FollowService followService;

    public User() {
        init();
        userId = modelFactory.nextUserId();
        userAuth = new UserAuth(userId);
        userAuth.addRole("client");
    }

    public User(UserAuth userAuth) {
        init();
        this.userAuth = userAuth;
        this.userId = userAuth.getUserId();
    }

    private User(Long userId) {
        init();
        this.userId = userId;
        this.userAuth = new UserAuth(userId);
    }

    public static User manageUserRegister(UserInfo userInfo) {
        User user = new User(userInfo.getUserId());
        user.userAuth.manage();
        user.kongService.kongUser(user.userAuth);
        userInfo.setBackground(user.getDefault().getBackground());
        user.setUserInfo(userInfo);
        user.addRole("management");
        user.newToken();
        return user.save();
    }

    public static Optional<User> phoneRegister(String phone, String password, String nickname, String avatar) {
        User user = new User();
        if (!user.setPhone(phone, true)) return Optional.empty();
        user.setPassword(password);
        user.kongService.kongUser(user.userAuth);
        user.getUserInfo().setNickname(nickname);
        if (avatar == null) {
            avatar = user.getDefault().getAvatar();
        }
        user.getUserInfo().setAvatar(avatar);
        user.getUserInfo().setBackground(user.getDefault().getBackground());
        user.newToken();
        user.save();
        user.publishUserRegister(UserRegisterEvent.RegisterType.PHONE);
        return Optional.of(user);
    }

    public static Optional<User> emailRegister(String email, String password, String nickname, String avatar) {
        User user = new User();
        if (!user.setEmail(email, false)) return Optional.empty();
        user.setPassword(password);
        user.kongService.kongUser(user.userAuth);
        user.getUserInfo().setNickname(nickname);
        if (avatar == null) {
            avatar = user.getDefault().getAvatar();
        }
        user.getUserInfo().setAvatar(avatar);
        user.getUserInfo().setBackground(user.getDefault().getBackground());
        user.addRole("limited");
        user.newToken();
        user.save();
        user.publishUserRegister(UserRegisterEvent.RegisterType.EMAIL);
        return Optional.of(user);
    }

    public static Optional<User> weiboRegister(String uid, String openToken) {
        User user = new User();

        return user.weiboAuth(uid, openToken)
                .map(userInfo -> {
                    user.kongService.kongUser(user.userAuth);
                    String avatar = user.pictureService.transAvatar(userInfo.getAvatar(), user.getUserId());
                    userInfo.setAvatar(avatar);
                    userInfo.setBackground(user.getDefault().getBackground());
                    user.setUserInfo(userInfo);
                    user.newToken();
                    user.publishUserRegister(UserRegisterEvent.RegisterType.WEIBO);
                    return user.save();
                });
    }

    public static Optional<User> wechatRegister(String openId, String unionId, String openToken, Integer type) {
        User user = new User();

        return user.wechatAuth(unionId, openId, openToken, type)
                .map(userInfo -> {
                    user.kongService.kongUser(user.userAuth);
                    String avatar = user.pictureService.transAvatar(userInfo.getAvatar(), user.getUserId());
                    userInfo.setAvatar(avatar);
                    userInfo.setBackground(user.getDefault().getBackground());
                    user.setUserInfo(userInfo);
                    user.newToken();
                    user.publishUserRegister(UserRegisterEvent.RegisterType.WECHAT);
                    return user.save();
                });
    }

    public static void delete(UserInfo userInfo) {
        User user = new User();
        List<ClubMember> clubMembers = user.clubMemberRepository.findByUserId(userInfo.getUserId());
        user.clubMemberRepository.delete(clubMembers);
        Optional<UserAuth> userAuth1 = user.userAuthRepository.findByUserId(userInfo.getUserId());
        if (userAuth1.isPresent()) {
            user.userAuthRepository.delete(userAuth1.get());
        }
        user.userInfoRepository.delete(userInfo);
    }

    public UserAuth getUserAuth() {
        if (userAuth == null) {
            userAuth = userAuthRepository.findByUserId(userId).orElse(new UserAuth(userId));
        }
        return userAuth;
    }

    public void setUserAuth(UserAuth userAuth) {
        if (this.userAuth == null && userAuth != null) {
            userAuth.setUserId(userId);
            this.userAuth = userAuth;
        }
    }

    public PasswordAuth getPasswordAuth() {
        if (passwordAuth == null) {
            passwordAuth = passwordAuthRepository.findByUserId(userId).orElse(new PasswordAuth(userId, null, null));
        }
        return passwordAuth;
    }

    public void setPasswordAuth(PasswordAuth passwordAuth) {
        if (this.passwordAuth == null && passwordAuth != null) {
            passwordAuth.setUserId(userId);
            this.passwordAuth = passwordAuth;
        }
    }

    public UserEmail getUserEmail() {
        if (userEmail == null) {
            userEmail = userEmailRepository.findByUserId(userId).orElse(new UserEmail(userId, null, false));
        }
        return userEmail;
    }

    public void setUserEmail(UserEmail userEmail) {
        if (this.userEmail == null && userEmail != null) {
            userEmail.setUserId(userId);
            this.userEmail = userEmail;
        }
    }

    public UserPhone getUserPhone() {
        if (userPhone == null) {
            userPhone = userPhoneRepository.findByUserId(userId).orElse(new UserPhone(userId, null, false));
        }
        return userPhone;
    }

    public void setUserPhone(UserPhone userPhone) {
        if (this.userPhone == null && userPhone != null) {
            userPhone.setUserId(userId);
            this.userPhone = userPhone;
        }
    }

    public UserInfo getUserInfo() {
        if (userInfo == null) {
            userInfo = userInfoRepository.findByUserId(userId).orElse(new UserInfo(userId, null, null, null, null));
        }
        return userInfo;
    }

    public void setUserInfo(UserInfo info) {
        if (this.userInfo == null && info != null) {
            info.setUserId(userId);
            this.userInfo = info;
        }
    }

    public UserInfo updateUserInfo(String nickname, String avatar, Integer gender, String province, String title) {
        getUserInfo().setNickname(nickname);
        getUserInfo().setAvatar(avatar);
        getUserInfo().setGender(gender);
        getUserInfo().setProvince(province);
        getUserInfo().setTitle(title);
        save();
        publishUserInfoUpdate(UserInfoUpdateEvent.UpdateType.CLIENT);
        return getUserInfo();
    }

    private void init() {

        userInfoRepository =
                ApplicationContextProvider.getBean(UserInfoRepository.class);

        passwordAuthRepository =
                ApplicationContextProvider.getBean(PasswordAuthRepository.class);

        weiboAuthRepository =
                ApplicationContextProvider.getBean(WeiboAuthRepository.class);

        wechatAuthRepository =
                ApplicationContextProvider.getBean(WechatAuthRepository.class);

        userAuthRepository = ApplicationContextProvider.getBean(UserAuthRepository.class);

        userPhoneRepository = ApplicationContextProvider.getBean(UserPhoneRepository.class);

        userEmailRepository = ApplicationContextProvider.getBean(UserEmailRepository.class);

        secureTokenRepository = ApplicationContextProvider.getBean(SecureTokenRepository.class);

        modelFactory = ApplicationContextProvider.getBean(ModelFactory.class);

        userService = ApplicationContextProvider.getBean(UserService.class);

        clubRepository = ApplicationContextProvider.getBean(ClubRepository.class);

        userFollowRepository = ApplicationContextProvider.getBean(UserFollowRepository.class);

        postRepository = ApplicationContextProvider.getBean(PostRepository.class);

        postLikeRepository = ApplicationContextProvider.getBean(PostLikeRepository.class);

        eventLikeRepository = ApplicationContextProvider.getBean(EventLikeRepository.class);

        eventProcessor = ApplicationContextProvider.getBean("eventProcessor", EventProcessor.class);

        clubBaseRepository = ApplicationContextProvider.getBean(ClubBaseRepository.class);

        clubMemberRepository = ApplicationContextProvider.getBean(ClubMemberRepository.class);

        commentRepository = ApplicationContextProvider.getBean(CommentRepository.class);

        clubEventMemberRepository = ApplicationContextProvider.getBean(ClubEventMemberRepository.class);

        clubEventRepository = ApplicationContextProvider.getBean(ClubEventRepository.class);

        eventOrderRepository = ApplicationContextProvider.getBean(EventOrderRepository.class);

        userEquipRepository = ApplicationContextProvider.getBean(UserEquipRepository.class);

        kongService = ApplicationContextProvider.getBean(KongService.class);

        pictureService = ApplicationContextProvider.getBean(PictureService.class);

        followService = ApplicationContextProvider.getBean(FollowService.class);

    }

    private Optional<UserInfo> weiboAuth(String uid, String openToken) {
        WeiboAuth weiboAuth = weiboAuthRepository
                .findByUid(uid)
                .orElse(new WeiboAuth(getUserId(), uid));
        Optional<UserInfo> userInfo = weiboAuth.auth(openToken);
        weiboAuthRepository.save(weiboAuth);
        return userInfo;
    }

    private Optional<UserInfo> wechatAuth(String unionId, String openId, String openToken, Integer type) {

        WechatAuth wechatAuth = wechatAuthRepository
                .findByOpenId(openId)
                .orElse(new WechatAuth(getUserId(), unionId, openId, type));
        Optional<UserInfo> userInfo = wechatAuth.auth(openToken);
        wechatAuthRepository.save(wechatAuth);
        return userInfo;
    }

    public User save() {
        if (userAuth != null) {
            userAuth = userAuthRepository.save(userAuth);
        }
        if (userEmail != null) {
            userEmail = userEmailRepository.save(userEmail);
        }
        if (userPhone != null) {
            userPhone = userPhoneRepository.save(userPhone);
        }
        if (userInfo != null) {
            userInfo = userInfoRepository.save(userInfo);
        }
        if (passwordAuth != null) {
            passwordAuth = passwordAuthRepository.save(passwordAuth);
        }
        return this;
    }

    public Optional<User> passwordLogin(String password) {
        if (!getPasswordAuth().checkPassword(password)) {
            return Optional.empty();
        } else {
            newToken();
            publishUserLogin(UserLoginEvent.LoginType.PASSWORD);
            return Optional.of(this);
        }
    }

    public Boolean setPhone(String phone, Boolean verified) {
        if (!userService.phoneExist(phone)) {
            getUserPhone().setPhone(phone);
            getUserPhone().setVerified(verified);
            userAuth.removeRole("limited");
            return true;
        } else {
            return false;
        }
    }

    public Boolean setEmail(String email, Boolean verified) {
        if (!userService.emailExist(email)) {
            getUserEmail().setEmail(email);
            getUserEmail().setVerified(verified);
            userAuth.removeRole("limited");
            return true;
        } else {
            return false;
        }
    }

    public Optional<User> setUsername(String username) {
        if (!userService.usernameExist(username)) {
            getPasswordAuth().setUsername(username);
            return Optional.of(this);
        } else {
            return Optional.empty();
        }
    }

    private User setPassword(String password) {
        getPasswordAuth().setPassword(password);
        return this;
    }

    public Optional<User> setPassword(String oldPassword, String newPassword) {
        if (!passwordLogin(oldPassword).isPresent()) {
            return Optional.empty();
        } else {
            setPassword(newPassword);
            return Optional.of(this);
        }
    }

    public Optional<User> resetPassword(String token, String password) {
        return secureTokenRepository
                .findByToken(token)
                .filter(secureToken ->
                        secureToken.getPhone() == null ?
                                secureToken.verifyEmail(getEmail()) :
                                secureToken.verifyPhone(getPhone()))
                .map(secureToken -> {
                    secureTokenRepository.save(secureToken);
                    setPassword(password);
                    userAuth.newToken();
                    return save();
                });
    }

    private void newToken() {
        kongService.kongDeleteJwt(userAuth);
        userAuth.newToken();
        kongService.kongJwt(userAuth);
    }

    public Optional<User> weiboLogin(String openToken) {
        if (weiboAuthRepository
                .findByUserId(userId)
                .flatMap(weiboAuth -> weiboAuth.auth(openToken))
                .isPresent()) {
            newToken();
            publishUserLogin(UserLoginEvent.LoginType.WEIBO);
            return Optional.of(this);
        } else {
            return Optional.empty();
        }
    }

    public Optional<User> wechatLogin(String openId, String openToken, Integer type) {
        if (wechatAuthRepository
                .findByOpenId(openId)
                .flatMap(wechatAuth -> wechatAuth.auth(openToken))
                .isPresent()) {
            newToken();
            publishUserLogin(UserLoginEvent.LoginType.WECHAT);
            return Optional.of(this);
        } else {
            return Optional.empty();
        }
    }

    public Optional<User> wechatExtLogin(String openId, String openToken, String unionId, Integer type) {
        WechatAuth wechatAuth = new WechatAuth(getUserId(), unionId, openId, type);
        wechatAuthRepository.save(wechatAuth);
        if (wechatAuth.auth(openToken).isPresent()) {
            newToken();
            publishUserLogin(UserLoginEvent.LoginType.WECHAT);
            return Optional.of(this);
        } else {
            return Optional.empty();
        }
    }

    public Optional<User> bindWehcat(String openId, String unionId, String openToken, Integer type) {
        if (userService.unionIdExist(unionId, type)) {
            return Optional.empty();
        } else {
            wechatAuth(unionId, openId, openToken, type);
            return Optional.of(this);
        }
    }

    public Optional<User> bindWeibo(String uid, String accessToken) {
        if (userService.uidExist(uid)) {
            return Optional.empty();
        } else {
            weiboAuth(uid, accessToken);
            return Optional.of(this);
        }

    }

    public Boolean joinClub(Long clubId) {
        return clubRepository
                .findByClubId(clubId)
                .map(club -> {
                    club.addAndSaveMember(getUserInfo(), ClubMemberType.MEMBER);
                    club.save();
                    publishUserJoinClub(clubId);
                    return true;
                }).orElse(false);
    }
    public Boolean founderClub(Long clubId) {
        return clubRepository
                .findByClubId(clubId)
                .map(club -> {
                    club.addAndSaveMember(getUserInfo(), ClubMemberType.FOUNDER);
                    club.save();
                    publishUserJoinClub(clubId);
                    return true;
                }).orElse(false);
    }
    public Boolean leaveClub(Long clubId) {
        Optional<Club> clubOptional = clubRepository.findByClubId(clubId);
        if (clubOptional.isPresent()) {
            clubOptional.get().removeMember(getUserId());
            publishUserLeaveClub(clubId);
            return true;
        } else {
            return false;
        }
    }

    public Boolean follow(Long followerId) {
        return !userService
                .isFollowed(getUserId(), followerId) &&
                userService.userIdExist(followerId) &&
                userFollowRepository
                        .save(new UserFollow(getUserId(), followerId)) != null;
    }

    public Boolean unFollow(Long followerId) {
        if (userService.isFollowed(getUserId(), followerId)) {
            userFollowRepository.deleteByFolloweeIdAndFollowerId(getUserId(), followerId);
            return true;
        } else {
            return false;
        }
    }


    public Boolean checkToken(String accessToken) {
        return userAuth.checkToken(accessToken);
    }

    public String getRole() {
        return userAuth.getRole();
    }

    public Boolean checkRole(String role) {
        return userAuth.checkRole(role);
    }

    public void addRole(String role) {
        userAuth.addRole(role);
    }

    public void removeRole(String role) {
        userAuth.removeRole(role);
    }

    public Long getUserId() {
        return userId;
    }

    public Long getUsersId() {
        return userInfo.getUserId();
    }

    public String getAccessToken() {
        return userAuth.getAccessToken();
    }

    public List<ClubBase> getClubs(Pageable pageable) {
        List<Long> clubIds = clubMemberRepository
                .findByUserId(getUserId(), pageable)
                .stream()
                .map(ClubMember::getClubId)
                .collect(Collectors.toList());
        if (clubIds.isEmpty()) {
            return new ArrayList<>();
        } else {
            return clubBaseRepository.findByClubIds(clubIds);
        }
    }

    public List<ClubMember> getManageClubs() {
        return clubMemberRepository
                .findByUserIdAndRankNot(getUserId(), ClubMemberType.MEMBER);
    }

    public String getEmail() {
        return getUserEmail().getEmail();
    }

    public String getPhone() {
        return getUserPhone().getPhone();
    }

    public Post postTo(Long clubId, Integer postType, List<ContentPart> contentParts) {
        Post post = new Post(clubId, getUserId(), postType, contentParts);
        post.save();
        publishUserPost(clubId, post.getPostId(), UserPostType.getPostType(postType),post.getUserPost().getContents());
        return post;
    }

    private void publishUserLogin(UserLoginEvent.LoginType type) {
        eventProcessor.publish(new UserLoginEvent(getUserId(), type));
    }

    private void publishUserRegister(UserRegisterEvent.RegisterType type) {
        eventProcessor.publish(new UserRegisterEvent(getUserId(), type,getUserInfo().getNickname(),getUserInfo().getAvatar(),getUserInfo().getGender(),getUserInfo().getProvince(),getUserInfo().getTitle()));
    }

    private void publishUserJoinClub(Long clubId) {
        eventProcessor.publish(new UserJoinClubEvent(getUserId(), clubId));
    }

    private void publishUserLeaveClub(Long clubId) {
        eventProcessor.publish(new UserLeaveClubEvent(getUserId(), clubId));
    }

    private void publishUserPost(Long clubId, Long postId, UserPostType postType,List<ContentPart> contentParts) {
        eventProcessor.publish(new UserPostEvent(getUserId(), clubId, postId, postType, PostEventType.CLIENT,contentParts));
    }

    private void publishUserInfoUpdate(UserInfoUpdateEvent.UpdateType type) {
        eventProcessor.publish(new UserInfoUpdateEvent(getUserId(), type,getUserInfo().getNickname(),getUserInfo().getAvatar(),getUserInfo().getGender(),getUserInfo().getProvince(),getUserInfo().getTitle()));
    }

    public UserInfoTokenVO getUserInfoTokenVO() {
        return new UserInfoTokenVO(getClubId(),getUserId(),
                getAccessToken(),
                getRole(),
                getUserInfo(),
                getUserPhone(),
                getUserEmail());
    }


    public List<FollowVO> getFollowees(Long viewerId, Pageable pageable) {
        return userFollowRepository
                .findByFollowerId(getUserId(), pageable)
                .stream()
                .map(userFollow -> followService.getFollowVO(userFollow.getFolloweeId(), viewerId))
                .collect(Collectors.toList());
    }

    public List<FollowVO> getFollowers(Long viewerId, Pageable pageable) {
        return userFollowRepository
                .findByFolloweeId(getUserId(), pageable)
                .stream()
                .map(userFollow -> followService.getFollowVO(userFollow.getFollowerId(), viewerId)).collect(Collectors.toList());
    }

    public List<UserPostVO> getUserPosts(Long viewerId, Pageable pageable) {
        return postRepository
                .findByUserId(getUserId(), pageable)
                .map(post -> post.getUserPostVO(viewerId))
                .collect(Collectors.toList());
    }

    public List<UserCommentPostVO> getUserComments(Long viewerId, Pageable pageable) {
        return postRepository
                .findCommentedPostByUserId(userId, pageable)
                .map(post ->
                        new UserCommentPostVO(post.getUserPostVO(viewerId),
                                commentRepository.findVOByUserIdAndPostId(userId, post.getPostId()))
                ).collect(Collectors.toList());
    }

    public List<ClubEventVO> getEvents(Pageable pageable) {
        return clubEventMemberRepository
                .findByUserIdOrderByEventIdDesc(getUserId(), pageable)
                .stream()
                .map(ClubEventMember::getEventId)
                .map(eventId -> clubEventRepository.findByEventId(eventId).get())
                .map(ClubEvent::getEventVO)
                .collect(Collectors.toList());
    }

    public List<ClubEventVO> getLikeEvents(Pageable pageable) {
        return eventLikeRepository
                .findByUserId(getUserId(), pageable)
                .stream()
                .map(EventLike::getEventId)
                .map(eventId -> clubEventRepository.findByEventId(eventId).get())
                .map(ClubEvent::getEventVO)
                .collect(Collectors.toList());
    }

    public List<UserPostVO> getLikePosts(Long viewerId, Pageable pageable) {
        return postLikeRepository
                .findByUserId(getUserId(), pageable)
                .stream()
                .map(PostLike::getPostId)
                .map(postId -> postRepository.findByPostId(postId).get())
                .map(post -> post.getUserPostVO(viewerId))
                .collect(Collectors.toList());
    }

    public void logout() {
        kongService.kongDeleteJwt(userAuth);
        userAuth.setAccessToken(null);
        save();
    }

    public UserProfileVO getProfileVO(Long viewerId) {
        UserInfo userInfo = getUserInfo();
        List<String> clubs = getClubs(new PageRequest(0, 3))
                .stream()
                .map(ClubBase::getClubName)
                .collect(Collectors.toList());
        int orderCount = 0;
        if (getUserId().equals(viewerId)) {
            orderCount = eventOrderRepository.countByUserId(getUserId());
        }
        int equipCount = userEquipRepository.countByUserId(getUserId());
        return new UserProfileVO(getUserId(),
                userInfo.getNickname(),
                userInfo.getAvatar(),
                userInfo.getBackground() != null && !userInfo.getBackground().equals("") ? userInfo.getBackground() : getDefault().getBackground(),
                userInfo.getGender(),
                userInfo.getProvince(),
                userInfo.getTitle(),
                clubs,
                userFollowRepository.countByFolloweeId(getUserId()),
                userFollowRepository.countByFollowerId(getUserId()),
                postLikeRepository.countByUserId(getUserId()) + eventLikeRepository.countByUserId(getUserId()),
                postRepository.countByUserId(getUserId()),
                commentRepository.countByUserId(getUserId()),
                clubEventMemberRepository.countByUserId(getUserId()),
                orderCount,
                equipCount,
                userFollowRepository.existsByFolloweeId(getUserId()));
    }

    public FollowVO getFollowVO(Long viewerId) {
        return new FollowVO(
                getUserId(),
                getUserInfo().getNickname(),
                getUserInfo().getAvatar(),
                followService.isFollow(getUsersId())
        );
    }

    public DefaultSettings getDefault() {
        return userService.getDefault();
    }

	public Long getClubId() {
		return clubId;
	}

	public void setClubId(Long clubId) {
		this.clubId = clubId;
	}
    
    
}
